package com.flyco.modules.pms.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.flyco.common.api.vo.Result;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.common.util.oConvertUtils;
import com.flyco.modules.pms.entity.PmsProduct;
import com.flyco.modules.pms.entity.PmsProductPics;
import com.flyco.modules.pms.entity.PmsSkuStock;
import com.flyco.modules.pms.entity.stmJdProductBase;
import com.flyco.modules.pms.mapper.PmsProductMapper;
import com.flyco.modules.pms.mapper.PmsProductPicsMapper;
import com.flyco.modules.pms.mapper.PmsSkuStockMapper;
import com.flyco.modules.pms.model.ProductUnitSpec;
import com.flyco.modules.pms.service.IPmsProductService;
import com.flyco.modules.pms.service.IPmsSkuStockService;
import com.flyco.modules.pms.service.IstmJdProductBaseService;
import com.flyco.modules.pms.vo.PmsProductExportVO;
import com.flyco.modules.pms.vo.PmsProductPicsVO;
import com.flyco.modules.pms.vo.PmsProductSkuForOrderVO;
import com.flyco.modules.pms.vo.PmsProductSkuVO;
import com.flyco.modules.stm.entity.StmStoreInfo;
import com.flyco.modules.stm.service.IStmStoreInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.sql.rowset.BaseRowSet;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 商品信息
 * @Author: flyco
 * @Date: 2019-11-19
 * @Version: V1.0
 */
@Slf4j
@Service
public class PmsProductServiceImpl extends ServiceImpl<PmsProductMapper, PmsProduct> implements IPmsProductService {
    @Autowired
    private PmsProductMapper pmsProductMapper;
    @Autowired
    private PmsSkuStockMapper pmsSkuStockMapper;
    @Autowired
    private PmsProductPicsMapper pmsProductPicsMapper;
    @Autowired
    private IPmsSkuStockService pmsSkuStockService;
    @Autowired
    private IStmStoreInfoService stmStoreInfoService;
    @Autowired
    private IstmJdProductBaseService productBaseService;

    @Override
    public Result<?> toNetStock(Integer brandCategory) {
        //获取需要初始化库存商品的店铺
        Map<Long, List<StmStoreInfo>> storeMap = getStoreMap(brandCategory);
        if (storeMap.isEmpty()) {
            return Result.ok("没有要执行的内容");
        }

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Date date = new Date();

        //网点补充库存商品数
        processNetStock(storeMap, sysUser.getRealname(), date);

        return Result.ok("执行成功");
    }

    /**
     * 网点补充库存商品数
     * storeMap  key=经销商storeId，value=需要补充库存商品数的网点
     */
    private void processNetStock(Map<Long, List<StmStoreInfo>> storeMap, String realName, Date date) {
        storeMap.forEach((storeId, list) -> {
            //查询经销商的库存商品
            List<PmsSkuStock> skuStocks = pmsSkuStockService.list(Wrappers.lambdaQuery(PmsSkuStock.class).eq(PmsSkuStock::getStoreId, storeId).eq(PmsSkuStock::getCancelFlag, 0));

            //查询网点的库存商品(只查询storeId和productId)
            Map<Long, List<Long>> collect = pmsSkuStockService.list(Wrappers.lambdaQuery(PmsSkuStock.class).select(PmsSkuStock::getStoreId, PmsSkuStock::getProductId)
                            .in(PmsSkuStock::getStoreId, list.stream().map(StmStoreInfo::getStoreId).collect(Collectors.toList())).eq(PmsSkuStock::getCancelFlag, 0))
                    .stream().collect(Collectors.groupingBy(PmsSkuStock::getStoreId, Collectors.mapping(PmsSkuStock::getProductId, Collectors.toList())));

            //分别比对，初始化库存商品信息
            list.forEach(one -> {
                initSkuProduct(skuStocks, one.getStoreId(), collect.get(one.getStoreId()), realName, date);
            });
        });
    }

    /**
     * 对比经销商和网点的库存商品数，网点没有的库存商品数补充上
     *
     * @param skuStocks        经销商库存商品信息
     * @param netSkuProductIds 网点存在的商品id
     */
    private void initSkuProduct(List<PmsSkuStock> skuStocks, Long netStoreId, List<Long> netSkuProductIds, String realName, Date date) {
        List<PmsSkuStock> collect;
        if (netSkuProductIds != null) {
            //找出网点没有的库存商品
            collect = skuStocks.stream().filter(q -> !netSkuProductIds.contains(q.getProductId())).collect(Collectors.toList());
        } else {
            //为空，说明网点一个库存商品也没有，全部都要初始化
            collect = skuStocks;
        }

        //经销商删除了商品，比网点商品多，这里会是空
        if (collect.isEmpty()) {
            return;
        }

        //网点库存初始化数据
        List<PmsSkuStock> skuStockList = collect.stream().map(one -> {
            PmsSkuStock skuStock = new PmsSkuStock();
            skuStock.setStoreId(netStoreId);
            skuStock.setProductId(one.getProductId());
            skuStock.setSkuCode(one.getSkuCode());
            skuStock.setSapItemCode(one.getSapItemCode());
            skuStock.setSkuUnit(one.getSkuUnit());
            skuStock.setSkuSpec(one.getSkuSpec());
            skuStock.setCreateTime(date);
            skuStock.setCreateBy(realName);
            return skuStock;
        }).collect(Collectors.toList());
        //保存网点初始化数据到数据库
        pmsSkuStockService.saveBatch(skuStockList);
    }

    /**
     * 返回需要补充库存商品数的经销商和网点
     * key=经销商storeId，value=需要补充库存商品数的网点
     */
    private Map<Long, List<StmStoreInfo>> getStoreMap(Integer brandCategory) {
        //需要补充库存商品数的数据，key=经销商storeId，value=需要补充库存商品数的网点
        Map<Long, List<StmStoreInfo>> storeMap = new HashMap<>();

        //查询经销商和网点
        List<StmStoreInfo> storeInfoList = stmStoreInfoService.list(Wrappers.lambdaQuery(StmStoreInfo.class)
                .select(StmStoreInfo::getStoreId, StmStoreInfo::getParentStoreId, StmStoreInfo::getStoreType)
                .in(StmStoreInfo::getStoreType, Arrays.asList(1, 2)).eq(StmStoreInfo::getStatus, 9).eq(StmStoreInfo::getBrandCategory, brandCategory));

        //查询经销商和网点的库存商品数
        Map<Long, Integer> rowCountMap = stmStoreInfoService.getStockProductCount().stream().collect(Collectors.toMap(PmsSkuStock::getStoreId, PmsSkuStock::getRowCount));

        //遍历所有的经销商
        storeInfoList.stream().filter(q -> q.getStoreType() == 1)
                //遍历每个经销商，查询他下面的网点
                .forEach(one -> {
                    //获取经销商的库存商品数量
                    Integer rowCount = rowCountMap.get(one.getStoreId());
                    //经销商有库存商品时，才做对比
                    if (rowCount != null) {
                        //找出该经销商的网点
                        List<StmStoreInfo> netStoreInfoList = storeInfoList.stream().filter(q -> Objects.equals(q.getParentStoreId(), one.getStoreId())).collect(Collectors.toList());
                        //网点不为空时，才做对比
                        if (!netStoreInfoList.isEmpty()) {
                            //找出网点的库存商品数量和经销商的不一样的
                            List<StmStoreInfo> collect = netStoreInfoList.stream().filter(oneNet -> rowCountMap.get(oneNet.getStoreId()) == null || !Objects.equals(rowCountMap.get(oneNet.getStoreId()), rowCount)).collect(Collectors.toList());
                            if (!collect.isEmpty()) {
                                storeMap.put(one.getStoreId(), collect);
                            }
                        }
                    }
                });

        return storeMap;
    }

    @Override
    @Transactional
    public void saveMain(PmsProduct pmsProduct, List<PmsSkuStock> pmsSkuStockList) {
        pmsProductMapper.insert(pmsProduct);
        for (PmsSkuStock entity : pmsSkuStockList) {
            //外键设置
            entity.setProductId(pmsProduct.getId());
            pmsSkuStockMapper.insert(entity);
        }
    }

    @Override
    @Transactional
    public void saveMainWithPics(List<PmsProductPicsVO> vos) {
        for (PmsProductPicsVO vo : vos) {
            PmsProduct pmsProduct = vo.getProduct();
            pmsProduct.setId(null);
            pmsProduct.setPublishStatus("0");
            pmsProduct.setWxStatus(0);
            pmsProduct.setCreateBy("");
            pmsProduct.setCreateTime(null);
            pmsProduct.setUpdateBy("");
            pmsProduct.setUpdateTime(null);
            pmsProductMapper.insert(pmsProduct);
            if (oConvertUtils.isNotEmpty(vo.getProductPics())) {
                for (PmsProductPics entity : vo.getProductPics()) {
                    //外键设置
                    entity.setProductId(pmsProduct.getId());
                    entity.setCreateBy("");
                    entity.setCreateTime(null);
                    entity.setUpdateBy("");
                    entity.setUpdateTime(null);
                    pmsProductPicsMapper.insert(entity);
                }
            }
        }
    }

    @Override
    @Transactional
    public void updateMain(PmsProduct pmsProduct, List<PmsSkuStock> pmsSkuStockList) {
        pmsProductMapper.updateById(pmsProduct);

        //1.先删除子表数据
        pmsSkuStockMapper.deleteByMainId(pmsProduct.getId());

        //2.子表数据重新插入
        for (PmsSkuStock entity : pmsSkuStockList) {
            //外键设置
            entity.setProductId(pmsProduct.getId());
            pmsSkuStockMapper.insert(entity);
        }
    }

    @Override
    @Transactional
    public void delMain(Long id) {
        pmsSkuStockMapper.deleteByMainId(id);
        pmsProductMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void delBatchMain(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            pmsSkuStockMapper.deleteByMainId((Long) id);
            pmsProductMapper.deleteById(id);
        }
    }

    @Override
    public PmsProduct getByProductSn(String productSn) {
        LambdaQueryWrapper<PmsProduct> query = new LambdaQueryWrapper<>();
        query.eq(PmsProduct::getProductSn, productSn);
        return this.getOne(query, false);
    }

    @Override
    public PmsProduct getBySkuCode(String skuCode) {
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PmsProduct::getSkuCode, skuCode);
        return getOne(wrapper);
    }


    @Override
    public List<PmsProductSkuVO> getProductSkuList() {
        return pmsSkuStockMapper.getProductSkuList();
    }

    @Override
    public List<PmsProductSkuForOrderVO> getProductSkuForOrderList(Long storeId, List<String> skuCodes) {
        return pmsSkuStockMapper.getProductSkuForOrderList(storeId, skuCodes);
    }

    @Override
    public List<PmsProductSkuForOrderVO> queryProductSkuList(List<Long> storeIds, List<String> productSns, List<String> skuCodes) {
        return pmsSkuStockMapper.queryProductSkuList(storeIds, productSns, skuCodes);
    }

    @Override
    public List<PmsProduct> queryLogicDeleted() {
        return this.queryLogicDeleted(null);
    }

    @Override
    public List<PmsProduct> queryLogicDeleted(LambdaQueryWrapper<PmsProduct> wrapper) {
        if (wrapper == null) {
            wrapper = new LambdaQueryWrapper<>();
        }
        wrapper.eq(PmsProduct::getDeleteStatus, "1");
        return pmsProductMapper.selectLogicDeleted(wrapper);
    }

    @Override
    public boolean revertLogicDeleted(List<String> productIds, PmsProduct updateEntity) {
        String ids = String.format("'%s'", String.join("','", productIds));
        return pmsProductMapper.revertLogicDeleted(ids, updateEntity) > 0;
    }

    @Override
    public Page<PmsProduct> getProductPage(Page<PmsProduct> page, Wrapper<PmsProduct> wrapper, Long partnerId) {
        return page.setRecords(pmsProductMapper.getProductPage(page, wrapper, partnerId));
    }

    @Override
    public Page<PmsProduct> getProductPageByStoreId(Page<PmsProduct> page, Wrapper<PmsProduct> wrapper, String storeId) {
        return page.setRecords(pmsProductMapper.getProductPageByStoreId(page, wrapper, storeId));
    }

    @Override
    public Page<PmsProduct> getProductPageByChannelId(Page<PmsProduct> page, Wrapper<PmsProduct> wrapper, String channelId) {
        return page.setRecords(pmsProductMapper.getProductPageByChannelId(page, wrapper, channelId));
    }

    @Override
    public List<PmsProduct> getProductListWithOutPartner(List<Long> ids) {
        return pmsProductMapper.getProductListWithOutPartner(ids);
    }

    @Override
    public List<PmsProductExportVO> getProductExportList(List<Long> idList, List<String> storeIdList) {
        return pmsProductMapper.getProductExportList(idList, storeIdList);
    }

    @Override
    public List<PmsProduct> getProductList(PmsProduct pmsProduct, Integer pageNo, Integer pageSize) {
        Integer startIndex = (pageNo - 1) * pageSize;
        if (pageNo != 1) {
            startIndex = (pageNo - 1) * pageSize + 1;
        }
        Integer endIndex = pageSize;
        return pmsProductMapper.getProductList(pmsProduct, startIndex, endIndex);
    }

    @Override
    public Integer getProductCount(PmsProduct pmsProduct) {

        return pmsProductMapper.getProductCount(pmsProduct);
    }

    @Override
    public List<PmsProduct> getProductListByProductName(String productName) {

        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(PmsProduct::getName, productName);
        return pmsProductMapper.selectList(wrapper);
    }

    /**
     * 批量通过旺店通的箱规更新产品表的箱规
     */
    @Override
    @Deprecated
    public void updateProductSpec() {

        Map<String, List<ProductUnitSpec>> specMap = getProductUnitSpec()
                .stream()
                .collect(Collectors.groupingBy(ProductUnitSpec::getSkuCode));

        List<PmsProduct> productList = pmsProductMapper.getAllProduct();
        List<PmsProduct> needUpdate = new ArrayList<>();
        productList.forEach(product -> {
            List<ProductUnitSpec> specList = specMap.get(product.getSkuCode());
            Boolean productUpdate = false;
            if (specList != null) {

                if (specList.size() == 1) {
                    //只有一条记录，可以把基本单位，售卖单位及规格全部进行更新。
                    ProductUnitSpec productUnitSpec = specList.get(0);
                    product.setUnit(productUnitSpec.getUnit());
                    product.setSkuUnit(productUnitSpec.getSkuUnit());
                    product.setSkuSpec(productUnitSpec.getSkuSpec());
                    needUpdate.add(product);
                } else {
                    //有多条的话只更新规格
                    for (ProductUnitSpec spec : specList) {
                        if (spec != null && Objects.equals(spec.getUnit(), product.getUnit())
                                && Objects.equals(spec.getSkuUnit(), product.getSkuUnit())
                                && !Objects.equals(spec.getSkuSpec(), product.getSkuSpec())) {
                            product.setSkuSpec(spec.getSkuSpec());
                            needUpdate.add(product);
//                            productUpdate = true;
                        }
                    }
                }


//                if (product.getSkuSpec() == null && !productUpdate ) {
//                    //如果没有找到换算单位，基本单位又跟售卖单位一致，则把规格设置成1
//                    product.setSkuSpec("1");
//                    needUpdate.add(product);
//                }
            }
        });

        needUpdate.forEach(product -> {
            pmsProductMapper.updateProductSpec(product.getId(), product.getSkuSpec());
        });

        log.info("updateProductSpec 更新箱规个数：" + needUpdate.size());
    }

    /**
     * 产品的售卖单位和基本单位的换算关系
     *
     * @return
     */
    @Override
    public List<ProductUnitSpec> getProductUnitSpec() {
        return pmsProductMapper.getProductUnitSpec();
    }

    /**
     * 当stm_jd_product_base有新的产品时，插入到pms_product，
     * 用户只需要在编辑时补充信息即可。新插入的产品属于下架状态
     */
    @Override
    public void autoInsertProduct() {

        List<PmsProduct> productList = getNeedInsertProduct();
        productList.forEach(product -> {
            if (product.getSkuUnit() != null && product.getUnit() != null && product.getSkuSpec() == null && product.getSkuUnit().equals(product.getUnit())) {
                product.setSkuSpec("1");
            }
            if (product.getSkuSpec() != null) {
                //防止没有规格的也插入到数据库引起其他问题
                pmsProductMapper.InsertProduct(product);
            }
        });
    }

    public List<PmsProduct> getNeedInsertProduct() {
        return pmsProductMapper.getNeedInsertProduct();
    }

    @Override
    public void autoUpdateProductSn() {

        pmsProductMapper.autoUpdateProduct();
    }

    @Override
    public void autoUpdateProductFromBase() {

        Map<String, PmsProduct> baseMap = pmsProductMapper.getJdProductBase().stream().collect(Collectors.toMap(PmsProduct::getSkuCode, a -> a));

        List<PmsProduct> productList = list();
        List<PmsProduct> needUpdate = new ArrayList<>();
        for (PmsProduct product : productList) {
            Boolean update = false;
            PmsProduct jdProductBase = baseMap.get(product.getSkuCode());
            if (jdProductBase != null) {
                if (!Objects.equals(jdProductBase.getName(), product.getName())) {
                    product.setName(jdProductBase.getName());
                    update = true;
                }
                if (!Objects.equals(jdProductBase.getUnit(), product.getUnit())) {
                    product.setUnit(jdProductBase.getUnit());
                    update = true;
                }
                if (!Objects.equals(jdProductBase.getSkuUnit(), product.getSkuUnit())) {
                    product.setSkuUnit(jdProductBase.getSkuUnit());
                    update = true;
                }
                if (!Objects.equals(jdProductBase.getSkuSpec(), product.getSkuSpec())) {
                    product.setSkuSpec(jdProductBase.getSkuSpec());
                    update = true;
                }
            }
            if (update) {
                needUpdate.add(product);
            }
        }
        if (!CollectionUtils.isEmpty(needUpdate)) {
            updateBatchById(needUpdate);
        }
    }

    @Override
    public List<PmsProduct> getByIds(List<Long> productId) {

        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PmsProduct::getId, productId)
                .eq(PmsProduct::getPublishStatus, 1);

        return list(wrapper);
    }

    @Override
    public List<PmsProduct> getAllByIds(List<Long> productId) {

        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PmsProduct::getId, productId);

        return list(wrapper);
    }

    @Override
    public List<PmsProduct> getProductListByName(String name) {

        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(PmsProduct::getProductSn, PmsProduct::getId, PmsProduct::getName, PmsProduct::getSkuCode);
        if (!StringUtils.isEmpty(name)) {
            wrapper.like(PmsProduct::getName, name);
        }
        return list(wrapper);
    }
}
